package cn.heygod.airsql.util;

import cn.heygod.airsql.annotation.Column;
import cn.heygod.airsql.exception.AirSqlException;
import cn.heygod.airsql.support.KeyFunction;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * @className: ColumnUtil
 * @author: Simon
 * @description: TODO
 * @date: 2024/1/27 1:44
 * @version: 1.0
 */
public class ColumnUtil {

    public static <T> String getName(KeyFunction<T, ?> fn) {
        Method writeReplaceMethod;
        SerializedLambda serializedLambda;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace", new Class[0]);
        } catch (NoSuchMethodException e) {
            throw new AirSqlException(e);
        }
        boolean isAccessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        try {
            serializedLambda = (SerializedLambda)writeReplaceMethod.invoke(fn, new Object[0]);
        } catch (IllegalAccessException|java.lang.reflect.InvocationTargetException e) {
            throw new AirSqlException(e);
        }
        String clsName = serializedLambda.getImplClass();
        String methodName = serializedLambda.getImplMethodName();
        Column column =  ClassUtil.getMethodAnnotation(clsName,methodName,Column.class);
        //如果方法没有注解，则找Field是否有注解，最后直接按Field名称进行转换
        if(column == null){
            //找Field
            writeReplaceMethod.setAccessible(isAccessible);
            String fieldName = methodName.substring("getX".length());
            //首字母小写
            fieldName = Character.toLowerCase(methodName.charAt(3)) + fieldName;
            column =  ClassUtil.getDeclaredFieldAnnotation(clsName,fieldName,Column.class);
            if(column == null){
                //通过方法推导fieldName，直接字符串转下划线风格
                return StringUtil.camelCaseToSnakeCase(fieldName).toLowerCase();
            }else {
                //通过本类声明字段的注解来获取
                return column.name();
            }
        }else {
            //通过方法（包含父类的public方法上的注解
            return column.name();
        }

    }
}
